package myutil

import (
	"fmt"
	"math"
	"math/rand"
	"strconv"
)

// ascii码[48-57]表示[0-9], [65-90]表示[A-Z], [97,122]表示[a,z]
const delta = 32                              // 大小写字母转换的 ASCII 差值（A-a=32）
const numberChars = "23456789"                // 不含易混淆数字（0,1）的数字字符集
const letterChars = "ABCDEFGHJKLMNPQRSTUVWXY" // 不含易混淆字母（i,l,o,z）的字母字符集
const specialChars = "!@#$%?&+="              // 特殊符合字符集

// RandomCharCode 随机生成包含‘数字+大写字母’的验证码
// length 字符长度，不能超出2-10范围
func RandomCharCode(length int) string {
	if length < 2 || length > 10 {
		panic("len 不符合2-10的长度要求")
	}

	//为了增大数字的出现
	allowedChars := numberChars + letterChars + numberChars

	// 构建结果字节切片（长度为 length）
	result := make([]byte, length)
	for i := range result {
		// 随机选择 allowedChars 中的字符
		idx := rand.Intn(len(allowedChars))
		result[i] = allowedChars[idx]
	}

	return string(result)
}

// RandomNumberCode 随机生成只含‘数字’的验证码
// length 字符长度，不能超出2-10范围
func RandomNumberCode(length int) string {
	if length < 2 || length > 10 {
		panic("length 不符合2-10的长度要求")
	}

	// 计算最大值：10^len（生成 [0, 10^len) 范围的随机数）
	upper := int64(math.Pow10(length))
	// 生成 [0, max) 范围的 int64 随机数
	num := rand.Int63n(upper)

	return fmt.Sprintf("%0"+strconv.Itoa(length)+"d", num)
}

// RandomPasswordCode 随机生成包含‘数字+大小写字母+特殊字符’的密码
// length 字符长度，不能超出4-20范围
// flag 取值：0-生成数字+大写字符，1-生成数字+大小写字符，2-生成数字+大小写字符+特殊字符
func RandomPasswordCode(length int, flag int) string {
	if length < 4 || length > 20 {
		panic("len 不符合4-20的长度要求")
	}

	//为了增大数字的出现
	allowedChars := numberChars + numberChars + letterChars
	letterPos := len(numberChars) * 2

	// 构建结果字节切片（长度为 length）
	arr := make([]byte, length)

	for i := range arr {
		// 随机选择 allowedChars 中的字符
		idx := rand.Intn(len(allowedChars))

		if idx >= letterPos { //表示选到的是字母字符
			switch flag {
			case 0: // 小写字母
				arr[i] = allowedChars[idx] + delta
			case 1, 2: // 可大可小
				arr[i] = allowedChars[idx] + uint8(RandomInt(0, 1)*delta)
			default:
				panic("invalid flag value, must be 0, 1, 2")
			}
		} else {
			arr[i] = allowedChars[idx] //数字字符
		}
	}

	//把普通字符随机替换为特殊字符
	if flag == 2 {
		var specialCount = (length - 1) / 4 //随机字符的概率
		var step = length / (specialCount + 1)

		for i := 0; i < specialCount; i++ {
			var index = step*(i+1) + i + RandomInt(-1, 1) //加一个干扰，移动[-1,0,1]
			arr[index%length] = specialChars[rand.Intn(len(specialChars))]
		}
	}
	return string(arr)
}

// RandomInt 生成[min, max]范围的随机整数
func RandomInt(min int, max int) int {
	if max <= min {
		panic("max 必须大于 min") // 确保范围有效
	}

	lower := min     // 左边界（包含）
	upper := max + 1 // 右边界（不包含）
	return rand.Intn(upper-lower) + lower
}
